// grammar describing many orthographies
// conversions between these orthographies (from an orthography to an orthography)

#ifndef RS_GRAMMAR_H
#define RS_GRAMMAR_H
#include "rs_string.h"
#include "rs_table.h"
#include "rs_affix.h"
using namespace std;


struct rs_pair {
    // pair of orthographies; converting from the source one(s) to the target one
    // so, there can be several orthographies to convert from (e.g. TO_US and TO_UK)
    // and only one target
    rs_string rsp_src_name;
    rs_string rsp_tgt_name;
    unsigned rsp_src_atix;  // source affix table index
    vector<text_cix> rsp_src_cix_v;   // source dictionary column indexes
    unsigned rsp_tgt_atix;  // target affix table index
    text_cix rsp_tgt_cix;   // target dictionary column index
    numb_cix freql_cix; // column FREQL
};


enum rs_stat_enum {
    rse_unknown,
    rse_dict,
    rse_stemmed,
      // todo: introduce more detailed statistics, more categories
    rse_last // this is the last value
};


class rs_statistics {
public:
    rs_statistics () {
        init_counters();
    };
    void increase (rs_stat_enum rse) {
        rss_counts[(unsigned) rse]++;
    }
    void init_counters() {
        for (unsigned i=0; i<(unsigned) rse_last; i++)
            rss_counts[i]=0;
    };
    unsigned counter (rs_stat_enum rse) const {
        return rss_counts[(unsigned) rse];
    }
    rs_table    cnv_missing;
    bool cnv_show_unknown; // flag: if word can't be translated, mark it
private:
    unsigned rss_counts[(unsigned) rse_last];
};


class rs_grammar {
public:
    rs_grammar (
        const rs_string& affix_cg_fname,
        const rs_string& proper_lc_fname,
        const rs_string& orthography);
    ~rs_grammar ();
    bool init_og_pair (
        rs_pair& ogp,
        const rs_string& src_og_name,
        const rs_string& tgt_og_name,
        bool allow_same);
    rs_affix& get_og (unsigned tix) { return rsg_affix[tix]; };
    const rs_affix& get_og (unsigned tix) const { return rsg_affix[tix]; };
    void add_ography (
        const rs_string& affix_cg_fname,
        rs_string abbreviation);
    rs_string get_og_name (unsigned tix) const { return rsg_affix[tix].get_og_name(); };
    rs_string get_og_abbr (unsigned atix) const {  // todo: remove unnecessary 'atix'
        if (rsg_dict == 0)
            return L"EN";
        else
            return rsg_dict->get_abbr();
    };

    bool is_valid() { return rsg_valid; };
    bool translate_any (
        const rs_string &src_word,
        text_cix src_cix,
        text_cix tgt_cix,
        numb_cix freql_cix,
        rs_string &tgt_word,
        bool& several) 
        const;
    bool is_unchanged (const rs_string& src) const {
        // returns true if 'src' is listed in table of unchanged words
        bool several;
        rs_rix rix;
        if (rsg_unchan==0)
            return false;
        rix = rsg_unchan->get_text_row_any (src, text_cix(0), several);
        return rix.is_valid();
    }
    size_t get_og_count () const { return rsg_og_count; };
    void check_dictionary (unsigned tix);
    bool convert_normalized_word (
        const rs_string& src_word,
        rs_string& tgt_word,
        bool check_composition,
        bool logging,
        rs_statistics& stat,
        const rs_pair& ogp);
    bool convert_composed_word (
        const rs_string& src,
        rs_string& cnv,
        bool logging,
        rs_statistics& stat,
        const rs_pair& ogp);
private:
    rs_grammar (const rs_grammar&);  // copy constructor, not implemened
    rs_grammar& operator= (const rs_grammar&); // copy assignment, not implemened
    bool has_valid_chars (const rs_string& word, const rs_string& valid) const;
// variables
    bool rsg_valid;
    rs_table* rsg_unchan;  // unchanged words like proper names; 1 column
    unsigned rsg_og_count;  // number of orthographies, == rsg_affix.size()
    vector<rs_affix> rsg_affix;
      // rsg_affix[0] is used for traditional orthograpies
      // rsg_affix[1] is used for reformed orthographies
    rs_table* rsg_dict;  // translation tables between TO and RO
      // has columns: OR_TO_US, OR_TO_UK, OR_SP, etc
};


#endif
